<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
define("RECAPTCHA_VERIFY_SERVER", "www.google.com");
class ReCaptchaResponse { var $is_valid; var $error; }

/**
 * Validate Class
 */
class CI_Validate {

	private $CI;
	// if array, first element is for php, second is js
	private $regex = array(
			'email'    => '/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/'
		,	'password' => '/^(?=.*(\d|\W))/' // at least one non-alphabetical character
	);

	/**
	 *  Costructor
	 */
	public function __construct()
	{
		$this->CI =& get_instance();

		$this->CI->layout->add_js_file("validate.js");
		$this->CI->lang->load("validate");
	}

	// --------------------------------------------------------------------

	/**
	 *  Tests a Regex Match
	 *
	 * Uses the internal regex patterns to try to get a match
	 * Returns true on successful match
	 *
	 */
	function regex($str, $regex)
	{
		$r = '';

		if(!isset($this->regex[$regex])) {
			return false;
		}

		if(!is_array($this->regex[$regex])) {
			$r = $this->regex[$regex];
		} else {
			$r = $this->regex[$regex][0];
		}

		if(preg_match($r, $str)) {
			return true;
		} else {
			return false;
		}
	}

	// --------------------------------------------------------------------

	/**
	 *  Tests a Regex Match
	 *
	 * Uses the internal regex patterns to try to get a match
	 * Returns true on successful match
	 *
	 */
	function strlen($str, $regex)
	{
		strlen(entities_to_ascii());
	}

	// --------------------------------------------------------------------

	/**
	 *  Run
	 *
	 * Runs a validation array to return if its successful
	 *
	 */
	function run($arr=array())
	{
		$r = array('success' => true, 'msg' => array());

		foreach($arr as $id => $a)
		{
			// Required
			if($a['min'] == 1) {
				if(strlen(trim($this->CI->input->post($id))) < 1) {
					$r['success'] = false;
					$r['msg'][$id] = $this->CI->lang->line('error_validate_required');
				}
			}
			// Minimum length
			elseif($a['min'] > 1) {
				if(strlen($this->CI->input->post($id)) < $a['minimum']) {
					$r['success'] = false;
					$r['msg'][$id] = sprintf($this->CI->lang->line('error_validate_minimum'), $a['minimum']);
				}
			}

			// Manimum length
			if($a['maximum'] > 0) {
				if(strlen($this->CI->input->post($id)) > $a['maximum']) {
					$r['success'] = false;
					$r['msg'][$id] = sprintf($this->CI->lang->line('error_validate_maximum'), $a['maximum']);
				}
			}

			// Ajax Match
			if(!empty($a['ajax'])) {
				foreach($a['regex'] as $r) {
					if(!$this->regex($this->CI->input->post($id), $r)) {
						$r['success'] = false;
						$r['msg'][$id] = $this->CI->lang->line('error_validate_'.$r);
					}
				}
			}

			// Match another field (case sensitive)
			if($a['match']) {
				if($this->CI->input->post($id) !== $this->CI->input->post($a['match'])) {
					$r['success'] = false;
					$r['msg'][$id] = sprintf($this->CI->lang->line('error_validate_match'), $arr[$a['match']]['label']);
				}
			}

			// Captcha, validate against server
			if($a['type'] == 'captcha') {

				$captcha = $this->recaptcha_check_answer(
							$this->CI->input->ip_address()
						,	$this->CI->input->post('recaptcha_challenge_field')
						,	$this->CI->input->post('recaptcha_response_field')
				);

				if(!$captcha->is_valid) {
					$r['success'] = false;

					switch($captcha->error) {

						case 'invalid-site-private-key':
							$r['msg'][$id] = $this->CI->lang->line('captcha_invalid_key');
						break;

						default:
							$r['msg'][$id] = $this->CI->lang->line('captcha_error');
						break;

					}
				} else {
					$this->CI->layout->data['reload_captcha'] = true;
				}

			}
		}

		return $r;
	}

	// --------------------------------------------------------------------

	/**
	 *  Parse
	 *
	 * Parses a validation array to output proper javascript vars
	 *
	 */
	function parse($arr=array())
	{
		foreach($arr as $id => $a)
		{
			// Required
			if($a['minimum'] == 1) {
				$this->_add_js_lang('error_validate_required');
			}

			// Minimum length
			if($a['minimum'] > 1) {
				$this->_add_js_lang('error_validate_minimum');
			}

			// Minimum length
			if($a['maximum'] > 0) {
				$this->_add_js_lang('error_validate_maximum');
			}

			// Ajax Match
			if(!empty($a['regex'])) {
				foreach($a['regex'] as $r) {
					$this->_add_js_lang('error_regex_'.$r);

					if(!is_array($this->regex[$r])) {
						$this->CI->layout->add_js_var(array('validate', 'regex', $r), $this->regex[$r]);
					} else {
						$this->CI->layout->add_js_var(array('validate', 'regex', $r), $this->regex[$r][1]);
					}
				}
			}

			// Match another field (case sensitive)
			if($a['match']) {
				$this->_add_js_lang('error_validate_match');
			}

			if($a['type'] == 'captcha') {
				$this->CI->layout->add_js_var(array('validate', 'recaptcha_public'), $this->CI->store->data('setting', 'recaptcha_public'));
			}
		}

		return true;
	}

	// Adds JS var for validation purposes
	function _add_js_lang($str) {
		$this->CI->layout->add_js_var(array('validate', $str), $this->CI->lang->line($str));
	}


	/*
	* This is a PHP library that handles calling reCAPTCHA.
	*    - Documentation and latest version
	*          http://recaptcha.net/plugins/php/
	*    - Get a reCAPTCHA API Key
	*          https://www.google.com/recaptcha/admin/create
	*    - Discussion group
	*          http://groups.google.com/group/recaptcha
	*
	* Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
	* AUTHORS:
	*   Mike Crawford
	*   Ben Maurer
	*
	* Permission is hereby granted, free of charge, to any person obtaining a copy
	* of this software and associated documentation files (the "Software"), to deal
	* in the Software without restriction, including without limitation the rights
	* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	* copies of the Software, and to permit persons to whom the Software is
	* furnished to do so, subject to the following conditions:
	*
	* The above copyright notice and this permission notice shall be included in
	* all copies or substantial portions of the Software.
	*
	* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	* THE SOFTWARE.
	*/

	/**
	* The reCAPTCHA server URL's
	*/

	/**
	* Encodes the given data into a query string format
	* @param $data - array of string elements to be encoded
	* @return string - encoded request
	*/
	function _recaptcha_qsencode ($data) {
			$req = "";
			foreach ( $data as $key => $value )
					$req .= $key . '=' . urlencode( stripslashes($value) ) . '&';

			// Cut the last '&'
			$req=substr($req,0,strlen($req)-1);
			return $req;
	}



	/**
	* Submits an HTTP POST to a reCAPTCHA server
	* @param string $host
	* @param string $path
	* @param array $data
	* @param int port
	* @return array response
	*/
	function _recaptcha_http_post($host, $path, $data, $port = 80) {

			$req = $this->_recaptcha_qsencode ($data);

			$http_request  = "POST $path HTTP/1.0\r\n";
			$http_request .= "Host: $host\r\n";
			$http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
			$http_request .= "Content-Length: " . strlen($req) . "\r\n";
			$http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
			$http_request .= "\r\n";
			$http_request .= $req;

			$response = '';
			if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
					die ('Could not open socket');
			}

			fwrite($fs, $http_request);

			while ( !feof($fs) )
					$response .= fgets($fs, 1160); // One TCP-IP packet
			fclose($fs);
			$response = explode("\r\n\r\n", $response, 2);

			return $response;
	}


	/**
	* Calls an HTTP POST function to verify if the user's guess was correct
	* @param string $privkey
	* @param string $remoteip
	* @param string $challenge
	* @param string $response
	* @param array $extra_params an array of extra variables to post to the server
	* @return ReCaptchaResponse
	*/
	function recaptcha_check_answer ($remoteip, $challenge, $response, $extra_params = array())
	{
		if ($remoteip == null || $remoteip == '') {
			die ("For security reasons, you must pass the remote ip to reCAPTCHA");
		}



			//discard spam submissions
			if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
					$recaptcha_response = new ReCaptchaResponse();
					$recaptcha_response->is_valid = false;
					$recaptcha_response->error = 'incorrect-captcha-sol';
					return $recaptcha_response;
			}

			$response = $this->_recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
											array (
													'privatekey' => $this->CI->store->data('setting', 'recaptcha_private'),
													'remoteip' => $remoteip,
													'challenge' => $challenge,
													'response' => $response
													) + $extra_params
											);

			$answers = explode ("\n", $response [1]);
			$recaptcha_response = new ReCaptchaResponse();

			if (trim ($answers [0]) == 'true') {
					$recaptcha_response->is_valid = true;
			}
			else {
					$recaptcha_response->is_valid = false;
					$recaptcha_response->error = $answers [1];
			}
			return $recaptcha_response;

	}

	/**
	* gets a URL where the user can sign up for reCAPTCHA. If your application
	* has a configuration page where you enter a key, you should provide a link
	* using this function.
	* @param string $domain The domain where the page is hosted
	* @param string $appname The name of your application
	*/
	function recaptcha_get_signup_url ($domain = null, $appname = null) {
		return "https://www.google.com/recaptcha/admin/create?" .  _recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname));
	}

}
// END Validate Class

/* End of file Validate.php */
/* Location: ./system/libraries/Validate.php */
